package com.ncu.spring.aop.advisor;

import java.lang.reflect.Method;

/**
 * 既是 Pointcut，又是 MethodMatcher
 * Pointcut：作为切点 加在方法上方 用来 查看当前方法是对哪个方法增强
 * MethodMatcher：判断该目标方法是否能被增强
 */
public class AspectJExpressionPointcut implements Pointcut, MethodMatcher {

    private String expression;

    public void setExpression(String expression) {
        this.expression = expression;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return this;
    }

    //判断一下 切点表达式 是否以 execution 或者 @annotation开头
    //如果不是就报错 是就继续判断
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        if (expression.startsWith("execution")) {
            return executionMatches(method, targetClass);
        } else if (expression.startsWith("@annotation")) {
            return annotationMatches(method, targetClass);
        } else {
            System.out.println("未知 expression，默认返回 true");
            return true;
        }
    }

    /**
     * 解析这种："@annotation(org.springframework.transaction.annotation.Transactional)"
     * 判断方法上是否有 expression 表达式里的注解就行了
     *
     * "@annotation(org.springframework.web.bind.annotation.GetMapping)"
     * 所有被GetMapping注解修饰的方法会织入advice
     */
    //切点表达式是注解开头 的判断逻辑：只要是注解开头这种切点表达式一律可以增强
    private boolean annotationMatches(Method method, Class<?> targetClass) {
        return true;
    }
    //切点表达式是execution开头 的判断逻辑：
    //只需要判断这个类中是否有方法名与这个切点表达式中有相同的字符串。 TODO：可以研究一下底层逻辑 将切点表达式的判断更加完善
    private boolean executionMatches(Method method, Class<?> targetClass) {
        String simpleName = targetClass.getSimpleName();
        if (expression.contains(simpleName)) {
            return true;
        }
        return false;
    }
}
